package com.panfeng.xcloud.boss.provider.member.service.impl;

import com.panfeng.xcloud.boss.provider.member.service.IUserVoiceCodeVerifyService;
import com.panfeng.xcloud.common.core.constants.RedisConstants;
import com.panfeng.xcloud.common.core.enums.ResponseStatusEnum;
import com.panfeng.xcloud.common.core.exceptions.BaseBizException;
import com.panfeng.xcloud.common.core.utils.RequestUtil;
import com.panfeng.xcloud.common.core.utils.VerifyCodeUtils;
import com.panfeng.xcloud.component.sms.SMSMsgSender;
import com.panfeng.xcloud.component.sms.config.MultiSmsPropConfig;
import com.panfeng.xcloud.component.sms.config.SmsCodeProp;
import com.panfeng.xcloud.component.sms.model.VoiceCodeReqDTO;
import com.panfeng.xcloud.component.sms.model.VoiceCodeRespDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class UserVoiceCodeVerifyServiceImpl implements IUserVoiceCodeVerifyService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private SMSMsgSender sMSMsgSender;

    @Autowired
    private MultiSmsPropConfig multiSmsPropConfig;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public VoiceCodeRespDTO voiceVerification(VoiceCodeReqDTO voiceCodeReqDTO, HttpServletRequest request) {
        String remoteAddr = RequestUtil.getRemoteAddr(request);
        this.checkSendVoiceCodeCount(voiceCodeReqDTO.getMobileNo(),remoteAddr);
        String verifyCode = VerifyCodeUtils.generateNumVerifyCode(6);
        String content = "您好，您的验证码是" + verifyCode;
        voiceCodeReqDTO.setContent(content);
        VoiceCodeRespDTO voiceCodeRespDTO = sMSMsgSender.voiceSendAndGet(voiceCodeReqDTO);
        String verifyingCodeCacheKey = RedisConstants.XDCLOUD_BOSS_VOICE_VERIFYINGCODE_PREFIX + voiceCodeReqDTO.getMobileNo() + "&" + voiceCodeReqDTO.getVoiceCodeBizType();
        stringRedisTemplate.opsForValue().set(verifyingCodeCacheKey, verifyCode, 5 , TimeUnit.MINUTES);
        return voiceCodeRespDTO;
    }

    /**
     * 语音次数校验
     *
     * @param mobileNo
     * @param ipAddr
     */
    private void checkSendVoiceCodeCount(String mobileNo, String ipAddr) {
        String mobileSmsCountKey = RedisConstants.XDCLOUD_BOSS_VOICE_MOBILESMSCOUNT_PREFIX + mobileNo;
        String ipSmsCountKey = RedisConstants.XDCLOUD_BOSS_VOICE_IPSMSCOUNT_PREFIX + ipAddr + "&" + mobileNo;
        String totalSmsCountKey = RedisConstants.XDCLOUD_BOSS_VOICE_TOTALSMSCOUNT_PREFIX + "&" + mobileNo +  "total";
        String sendSmsRateKey = RedisConstants.XDCLOUD_BOSS_VOICE_SENDSMSRATE_PREFIX + ipAddr + "&" + mobileNo;
        SmsCodeProp smsCodeProp = multiSmsPropConfig.getSmsCodeProp();

        Integer sendSmsRateCount = (Integer) redisTemplate.opsForValue().get(sendSmsRateKey);
        if (sendSmsRateCount != null) {
            log.error(">>> 语音验证码-验证次数校验-操作频率过快 ipAddr={}, mobile={}", ipAddr, mobileNo);
            throw new BaseBizException(ResponseStatusEnum.SENDSMSRATE_FAIL,"语音次数校验-操作频率过快");
        } else {
            redisTemplate.opsForValue().set(sendSmsRateKey, 1, 1, TimeUnit.MINUTES);
        }
        Integer mobileSmsCount = (Integer) redisTemplate.opsForValue().get(mobileSmsCountKey);
        if (mobileSmsCount != null && mobileSmsCount > smsCodeProp.getMobileMaxSendCount()) {
            log.error(">>> 语音验证码-验证次数校验-当天语音发送数上限 ipAddr={}, mobile={}", ipAddr, mobileNo);
            throw new BaseBizException(ResponseStatusEnum.MOBILESMSCOUNT_FAIL,"语音次数校验-当天语音发送数上限");
        } else {
            redisTemplate.opsForValue().set(mobileSmsCountKey, mobileSmsCount == null ? 1 : mobileSmsCount + 1, 1, TimeUnit.DAYS);
        }
        Integer ipSmsCount = (Integer) redisTemplate.opsForValue().get(ipSmsCountKey);
        if (ipSmsCount != null && ipSmsCount > smsCodeProp.getIpMaxSendCount()) {
            log.error(">>> 语音验证码-验证次数校验-IP当天语音发送数上限 ipAddr={}, mobile={}", ipAddr, mobileNo);
            throw new BaseBizException(ResponseStatusEnum.IPSMSCOUNT_FAIL,"语音次数校验-IP当天语音发送数上限");
        } else {
            redisTemplate.opsForValue().set(ipSmsCountKey, ipSmsCount == null ? 1 : ipSmsCount + 1, 1, TimeUnit.DAYS);
        }
        Integer totalSmsCount = (Integer) redisTemplate.opsForValue().get(totalSmsCountKey);
        if (totalSmsCount != null && totalSmsCount > smsCodeProp.getTotalMaxSendCount()) {
            log.error(">>> 语音验证码-验证次数校验-当天语音发送数上限 ipAddr={}, mobile={}", ipAddr, mobileNo);
            throw new BaseBizException(ResponseStatusEnum.TOTALSMSCOUNT_FAIL,"语音次数校验-当天语音发送数上限");
        } else {
            redisTemplate.opsForValue().set(totalSmsCountKey, totalSmsCount == null ? 1 : totalSmsCount + 1, 1, TimeUnit.DAYS);
        }
    }

}
